package screen

import (
	"fmt"
	"gexcel/pkg/excel"
	"github.com/gdamore/tcell"
	"github.com/gdamore/tcell/encoding"
	"os"
	"strconv"
	"strings"
	"unicode"
)

var (
	white                = tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.ColorRed)
	StyleBlackLine       = tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorWhite)
	StyleBlackWord       = tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorWhite)
	StyleLogInfo         = tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.ColorGreen)
	StyleLogDebug        = tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.ColorOrange)
	StyleLogWarn         = tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.ColorOrangeRed)
	StyleLogError        = tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.ColorRed)
	StyleBackgroundColor = tcell.StyleDefault.Background(tcell.ColorWhite)
)

const (
	PageSheetChoice = iota + 1
	PageSheetData
	PageSheetDataEdit
	PageStyleShow
)

type Screen struct {
	ScreenObj                tcell.Screen
	ScreenWidth              int
	ScreenHeight             int
	ExcelObj                 *excel.Excel
	LogStr                   string
	LogType                  string
	EventMap                 map[string]func()
	BtnLast                  string
	ScreenPaintFuncList      []PaintFunc
	PageCur                  int
	PageCurPaintFuncList     map[int][]PaintFunc
	SheetCur                 int
	SheetList                []string
	SheetData                [][]string
	SheetCellCurX            int
	SheetCellCurY            int
	SheetCellWidth           []int
	SheetDataLineNumberWidth int // 数据显示部分，左边显示行数的宽度
	SheetDataStartPointX     int
	SheetDataStartPointY     int
}

func NewScreen() *Screen {
	s, err := tcell.NewScreen()
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
	if err := s.Init(); err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
	return &Screen{ScreenObj: s, EventMap: make(map[string]func()), PageCurPaintFuncList: map[int][]PaintFunc{}}
}

func (s *Screen) EmitStr(x, y int, style tcell.Style, str string) {
	for _, c := range str {
		//s.ScreenObj.SetCell(x, y, style, c)
		s.ScreenObj.SetContent(x, y, c, nil, style)
		if unicode.Is(unicode.Han, c) { // 如果是汉字，就增加两个宽度
			x += 2
		} else if c >= 65281 && c <= 65374 {
			x += 2
		} else { // 如果是英文，就增加一个宽度
			x += 1
		}
	}
}

func (s *Screen) UpdateSheetDataLineNumberWidth() {
	p := s.ScreenHeight - s.SheetDataStartPointY - 2
	SheetDataLineNumberWidth := len(strconv.Itoa(p)) + 2
	if s.SheetDataLineNumberWidth != SheetDataLineNumberWidth {
		s.SheetDataLineNumberWidth = SheetDataLineNumberWidth
		s.LogDebug("调整行数显示宽度：" + strconv.Itoa(s.SheetDataLineNumberWidth))
	}
}

func (s *Screen) Refresh() {
	//s.ScreenObj.Clear()
	s.SetScreenBackgroundColor()

	//for _, PaintFunc := range s.ScreenPaintFuncList {
	//	PaintFunc.Run()
	//}
	if PaintFuncList, ok := s.PageCurPaintFuncList[s.PageCur]; ok {
		for _, PaintFunc := range PaintFuncList {
			PaintFunc.Run()
		}
	}
	s.ScreenObj.Sync()
	s.LogPrint()
}

// SetScreenBackgroundColor 设置整个终端的背景颜色
func (s *Screen) SetScreenBackgroundColor() {
	for i := 0; i < s.ScreenHeight; i++ {
		for j := 0; j < s.ScreenWidth; j++ {
			s.ScreenObj.SetContent(j, i, ' ', nil, StyleBackgroundColor)
		}
	}
	//for _, c := range 10 {
	//	//s.ScreenObj.SetCell(x, y, style, c)
	//	s.ScreenObj.SetContent(x, y, c, nil, style)
	//	if unicode.Is(unicode.Han, c) { // 如果是汉字，就增加两个宽度
	//		x += 2
	//	} else if c >= 65281 && c <= 65374 {
	//		x += 2
	//	} else { // 如果是英文，就增加一个宽度
	//		x += 1
	//	}
	//}
}

func (s *Screen) GetStrWidth(str string) (width int) {
	for _, c := range str {
		if unicode.Is(unicode.Han, c) { // 如果是汉字，就增加两个宽度
			width += 2
		} else if c >= 65281 && c <= 65374 {
			width += 2
		} else { // 如果是英文，就增加一个宽度
			width += 1
		}
	}
	return
}

// CutStrByWidth 带省略号的切断
func (s *Screen) CutStrByWidth(str string, widthLimit int) (strNew string) {
	widthStr, widthNew := s.GetStrWidth(str), 0
	if widthStr > widthLimit {
		for _, c := range str {
			if unicode.Is(unicode.Han, c) { // 如果是汉字，就增加两个宽度
				widthNew += 2
			} else if c >= 65281 && c <= 65374 {
				widthNew += 2
			} else { // 如果是英文，就增加一个宽度
				widthNew += 1
			}
			if widthNew > widthLimit-3 {
				return strNew + "..."
			}
			strNew += string(c)
		}
	} else {
		strNew = str + strings.Repeat(" ", widthLimit-widthStr)
	}
	return
}

func (s *Screen) EventRegister(Event string, Func func()) {
	s.EventMap[Event] = Func
}

func (s *Screen) Exit() {
	s.ScreenObj.Fini() // 退出前必须执行，否则无法正常恢复终端
	os.Exit(0)
}

func (s *Screen) Run() {
	encoding.Register()
	s.UpdateSheetDataLineNumberWidth()
	for {
		s.Refresh()
		s.ScreenObj.Show()
		ev := s.ScreenObj.PollEvent()
		switch ev := ev.(type) {
		case *tcell.EventResize:
			s.ScreenObj.Sync()
			s.ScreenWidth, s.ScreenHeight = s.ScreenObj.Size()
			s.LogDebug(fmt.Sprintf("EventResize: %v - %v", s.ScreenWidth, s.ScreenHeight))
			s.UpdateSheetDataLineNumberWidth()
		case *tcell.EventKey:
			s.LogInfo(fmt.Sprintf("按键按下：[%v][%v]", ev.Name(), ev.Key()))
			if Func, ok := s.EventMap[ev.Name()]; ok {
				Func()
			}
			s.BtnLast = ev.Name()
		}
	}
}
